package jf.collections;

import jf.closure.F1B;
import jf.closure.F1V;
import jf.closure.F2;
import jf.closure.F1;

import java.util.Iterator;

/**
 * @author alex
 * @date 16.05.2009
 */
public interface CollectionX<A> {
	/**
	 * Last element from list
	 *
	 * @return
	 */
	A last();

	/**
	 * first element from list
	 *
	 * @return
	 */
	A head();

	/**
	 * Find and return the first element of the list satisfying a predicate, if any.
	 *
	 * @param f closure for search
	 * @return Some if exists or None
	 */
	Option<A> find(F1B<A> f);

	/**
	 * Combines the elements of this list together using the binary function f, from right to left, and starting with the value b.
	 *
	 * @param b
	 * @param f
	 * @param <B>
	 * @return
	 */
	<B> B foldLeft(B b, F2<B, A, B> f);

	/**
	 * Combines the elements of this list together using the binary function f, from right to left, and starting with the value b.
	 *
	 * @param b
	 * @param f
	 * @param <B>
	 * @return
	 */
	<B> B foldRight(B b, F2<B, A, B> f);

	/**
	 * Tests if the predicate p is satisfied by all elements in this list.
	 *
	 * @param f
	 * @return
	 */
	boolean forall(F1B<A> f);

	/**
	 * Apply the given function f to each element of this list (while respecting the order of the elements).
	 *
	 * @param f
	 */
	void foreach(F1V<A> f);

	/**
	 * Return iterator from right to left (reversed normal)
	 *
	 * @return
	 */
	public Iterator<A> rightIterator();

	/**
	 * Return iterator from left to right (as normal)
	 *
	 * @return
	 */
	public Iterator<A> leftIterator();


	/**
	 * Format toString with next params
	 *
	 * @param delimeter
	 * @param head
	 * @param tail
	 * @return string that looks like head + <element1> + delimeter + <element2> + .. +<elementLast> + tail
	 */
	public String toString(String delimeter, String head, String tail);
}
